Advanced Data Visualization Theory DA-1 Prashanth.S 19MID0020

Data-sets used data-set1 : https://raw.githubusercontent.com/ScienceParkStudyGroup/r-lesson-based-on-ohi-data-training/gh-pages/data/ca.csv dat-set 2: https://www.kaggle.com/code/adhok93/zomato-eda-in-r/data?select=zomato.csv

Importing the libraries

library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ──────────────────────────── tidyverse 1.3.1 ──
✓ ggplot2 3.3.5     ✓ purrr   0.3.4
✓ tibble  3.1.6     ✓ dplyr   1.0.8
✓ tidyr   1.2.0     ✓ stringr 1.4.0
✓ readr   2.1.2     ✓ forcats 0.5.1
── Conflicts ─────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(plotly)

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
require(devtools)
Loading required package: devtools
Loading required package: usethis

US National Parks data-set

Importing the data-set

# National Parks in California
ca = read_csv("https://raw.githubusercontent.com/ScienceParkStudyGroup/r-lesson-based-on-ohi-data-training/gh-pages/data/ca.csv") 
Rows: 789 Columns: 7
── Column specification ─────────────────────────────────────────────
Delimiter: ","
chr (5): region, state, code, park_name, type
dbl (2): visitors, year

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(ca)

Analysing the data-type of the data

colnames(ca)
[1] "region"    "state"     "code"      "park_name" "type"     
[6] "visitors"  "year"     
str(ca)
spec_tbl_df [789 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ region   : chr [1:789] "PW" "PW" "PW" "PW" ...
 $ state    : chr [1:789] "CA" "CA" "CA" "CA" ...
 $ code     : chr [1:789] "CHIS" "CHIS" "CHIS" "CHIS" ...
 $ park_name: chr [1:789] "Channel Islands National Park" "Channel Islands National Park" "Channel Islands National Park" "Channel Islands National Park" ...
 $ type     : chr [1:789] "National Park" "National Park" "National Park" "National Park" ...
 $ visitors : num [1:789] 1200 1500 1600 300 15700 ...
 $ year     : num [1:789] 1963 1964 1965 1966 1967 ...
 - attr(*, "spec")=
  .. cols(
  ..   region = col_character(),
  ..   state = col_character(),
  ..   code = col_character(),
  ..   park_name = col_character(),
  ..   type = col_character(),
  ..   visitors = col_double(),
  ..   year = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 

Plot-1 –> ggplot2

Bar Plot

labs = c(
         'CHIS'='Channel Islands National Park',
         'DEVA'='Death Valley National Park',
         'JOTR'='Joshua Tree National Park',
         'KICA'='Kings Canyon National Park',
         'LAVO'='Lassen Volcanic National Park',
         'YOSE'='Yosemite National Park',
         'SEQU'='Sequoia National Park',
         'REDW'='Redwood National Park',
         'PINN'='Pinnacles National Park'
         )
bar_plot = ggplot(data=ca, aes(x = code, y = ..count.. / sum(..count..),fill = factor(code))) +
           geom_bar(color='black') + 
           labs(x = "National Parks", y = "Percentage of National Parks in the data-set", 
                title = "Occurence of the National Parks in the data-set") +
  
           scale_x_discrete(labels =labs)
           scale_y_continuous(labels = scales::percent)
<ScaleContinuousPosition>
 Range:  
 Limits:    0 --    1
           
bar_plot + coord_flip()

Yosemite National Parks and Sequoia National Park occurs more often in the data-set

Kernel Density Plot

density_plot = ggplot(data=ca, aes(x =log10(visitors))) +
                geom_density(fill = "indianred3") +
                labs(x = "Number of visitors", y="density", title="Kernal density of Visitors")
density_plot       

Plot-2 –> plotly

Scatter plot

t <- list(family = "Helvetica",size = 14,color = "blue")
t1 <- list(family = "Times New Roman",color = "red")
t2 <- list(family = "Courier New",size = 14,color = "green")
t3 <- list(family = 'Arial')
scatter_plot = plot_ly(data=ca, x=~year, y=~visitors,color = ~park_name, type='scatter',mode='markers') %>%
                       layout(
                          title= list(text = "<b>Year and Visitors"),
                          legend = list(title = list(text ='<b>National Parks')), 
                          xaxis  = list(title = list(text ='<b>Year')),
                          yaxis  = list(title = list(text ='<b>Visitors')),
                          plot_bgcolor='#e5ecf6')
scatter_plot
Warning in RColorBrewer::brewer.pal(N, "Set2") :
  n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors

Warning in RColorBrewer::brewer.pal(N, "Set2") :
  n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors

Warning in RColorBrewer::brewer.pal(N, "Set2") :
  n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors

Warning in RColorBrewer::brewer.pal(N, "Set2") :
  n too large, allowed maximum for palette Set2 is 8
Returning the palette you asked for with that many colors

Yosemite National Park secures a more number of visitors than any-other national parks.

Barchart

r_group_barchart = data.table::melt(ca, id.vars='park_name') %>%
plot_ly(x = ~park_name, y = ~value, type = 'bar', name = ~variable, color = ~variable) %>%
      layout(
          title= list(text = "<b>Total Distribution based on the Data-Set"),
          legend = list(title = list(text= '<b>Attribute')),
          xaxis  = list(title = list(text ='<b>Parks')),
          yaxis = list(title='Count', text='<b>Count'), barmode = 'group')
Warning in data.table::melt(ca, id.vars = "park_name") :
  The melt generic in data.table has been passed a spec_tbl_df and will attempt to redirect to the relevant reshape2 method; please note that reshape2 is deprecated, and this redirection is now deprecated as well. To continue using melt methods from reshape2 while both libraries are attached, e.g. melt.list, you can prepend the namespace like reshape2::melt(ca). In the next version, this warning will become an error.
r_group_barchart

Kings Canyon National Park secures the top in terms of region, state, national park.

Pie-chart

df_order = data.frame(table(ca$park_name))
df_order
pie_chart = plot_ly(type='pie', labels=df_order$Var1, values=df_order$Freq, 
                    textinfo='label+percent',insidetextorientation='radial') %>%
                    layout(
                          title= list(text = "<b>Order Distributions"),
                          legend = list(title = list(text= '<b>Order')))

pie_chart

Histogram Plots

histogram_plot = plot_ly(data = ca, x = ~(log(visitors)), name=~code,type="histogram") %>%
                  layout(
                          title= list(text = "<b>Total sleep time of Animals based on Vore"),
                          legend = list(title = list(text= '<b>Vore')),
                          xaxis  = list(title = list(text ='<b>Visitors')),
                          yaxis  = list(title = list(text ='<b>Count')))
histogram_plot

SEQU and LAVO national parks has more number of visitors

Donut Chart / Open Pie-Chart

df_vore = data.frame(table(ca$code))
df_vore
donut_chart = plot_ly(labels=df_vore$Var1, values=df_vore$Freq, 
                    textinfo='label+percent') %>%
                    add_pie(hole = 0.6) %>%
                    layout(
                          title= list(text = "<b>Order Distributions"),
                          legend = list(title = list(text= '<b>Order')))

donut_chart

SEQU, YOSE and KICA national parks has more number of visitors with respect to pie-chart.

Zomato data-set

Importing the data-set

library(dplyr)

Importing the data-set

df = read.csv('zomato.csv')
head(df)

Analysing the data-type of the data

names(df)
 [1] "Restaurant.ID"        "Restaurant.Name"     
 [3] "Country.Code"         "City"                
 [5] "Address"              "Locality"            
 [7] "Locality.Verbose"     "Longitude"           
 [9] "Latitude"             "Cuisines"            
[11] "Average.Cost.for.two" "Currency"            
[13] "Has.Table.booking"    "Has.Online.delivery" 
[15] "Is.delivering.now"    "Switch.to.order.menu"
[17] "Price.range"          "Aggregate.rating"    
[19] "Rating.color"         "Rating.text"         
[21] "Votes"               
str(df)
'data.frame':   9551 obs. of  21 variables:
 $ Restaurant.ID       : int  6317637 6304287 6300002 6318506 6314302 18189371 6300781 6301290 6300010 6314987 ...
 $ Restaurant.Name     : chr  "Le Petit Souffle" "Izakaya Kikufuji" "Heat - Edsa Shangri-La" "Ooma" ...
 $ Country.Code        : int  162 162 162 162 162 162 162 162 162 162 ...
 $ City                : chr  "Makati City" "Makati City" "Mandaluyong City" "Mandaluyong City" ...
 $ Address             : chr  "Third Floor, Century City Mall, Kalayaan Avenue, Poblacion, Makati City" "Little Tokyo, 2277 Chino Roces Avenue, Legaspi Village, Makati City" "Edsa Shangri-La, 1 Garden Way, Ortigas, Mandaluyong City" "Third Floor, Mega Fashion Hall, SM Megamall, Ortigas, Mandaluyong City" ...
 $ Locality            : chr  "Century City Mall, Poblacion, Makati City" "Little Tokyo, Legaspi Village, Makati City" "Edsa Shangri-La, Ortigas, Mandaluyong City" "SM Megamall, Ortigas, Mandaluyong City" ...
 $ Locality.Verbose    : chr  "Century City Mall, Poblacion, Makati City, Makati City" "Little Tokyo, Legaspi Village, Makati City, Makati City" "Edsa Shangri-La, Ortigas, Mandaluyong City, Mandaluyong City" "SM Megamall, Ortigas, Mandaluyong City, Mandaluyong City" ...
 $ Longitude           : num  121 121 121 121 121 ...
 $ Latitude            : num  14.6 14.6 14.6 14.6 14.6 ...
 $ Cuisines            : chr  "French, Japanese, Desserts" "Japanese" "Seafood, Asian, Filipino, Indian" "Japanese, Sushi" ...
 $ Average.Cost.for.two: int  1100 1200 4000 1500 1500 1000 2000 2000 6000 1100 ...
 $ Currency            : chr  "Botswana Pula(P)" "Botswana Pula(P)" "Botswana Pula(P)" "Botswana Pula(P)" ...
 $ Has.Table.booking   : chr  "Yes" "Yes" "Yes" "No" ...
 $ Has.Online.delivery : chr  "No" "No" "No" "No" ...
 $ Is.delivering.now   : chr  "No" "No" "No" "No" ...
 $ Switch.to.order.menu: chr  "No" "No" "No" "No" ...
 $ Price.range         : int  3 3 4 4 4 3 4 4 4 3 ...
 $ Aggregate.rating    : num  4.8 4.5 4.4 4.9 4.8 4.4 4 4.2 4.9 4.8 ...
 $ Rating.color        : chr  "Dark Green" "Dark Green" "Green" "Dark Green" ...
 $ Rating.text         : chr  "Excellent" "Excellent" "Very Good" "Excellent" ...
 $ Votes               : int  314 591 270 365 229 336 520 677 621 532 ...
bar_plot = ggplot(data=df, aes(x = `Rating.color`, y = ..count.. / sum(..count..),fill = factor(`Rating.color`))) +
           geom_bar(color='black') + 
           labs(x = "National Parks", y = "Percentage of National Parks in the data-set", 
                title = "Occurence of the National Parks in the data-set") +
  
           scale_y_continuous(labels = scales::percent)
           
bar_plot + coord_flip()

df %>%
  filter(Country.Code == 1) %>%
  select(Restaurant.ID) %>%
  unique() %>%
  nrow()
[1] 8652

There are 8652 restaurants operating in India

df %>% filter(Country.Code == 1) %>% select(Restaurant.ID,City) %>% unique() %>% group_by(City) %>% summarise(n=n()) %>%
  ggplot(aes(x=reorder(`City`,n),y=n))+ geom_bar(stat = 'identity',fill='#cb202d') +
  coord_flip() +
  theme(panel.background = element_blank(),
        strip.background = element_blank(),
        axis.title = element_text(color = '#2d2d2d'),
        strip.text.x = element_text(color='#2d2d2d',face='bold',size=10),
        plot.title = element_text(hjust=0.5,face='bold',size=15))+
        labs(x='City',y='Number of Restaurants',title="Number of Restaurants by City")

There are more restaurants in Delhi which operates with Zomato

df_india = df %>% filter(Country.Code == 1 & City == 'Agra')
head(df_india)
ggplot(data=df_india, aes(x=Longitude, y=Latitude),
       color='white') + 
       geom_polygon() + 
       scale_fill_viridis_d(option='A')

Plot-4 –> gganimate

library(gganimate)
library(gifski)

Animate –> Scatter Plot

scatter_plot_animate = ggplot(data=ca, aes(year, visitors)) + geom_point() +                
                       transition_states(park_name)
animate(scatter_plot_animate, renderer = gifski_renderer())

Rendering [=>------------------------------------------------] at 22 fps ~ eta:  4s
Rendering [==>-----------------------------------------------] at 22 fps ~ eta:  4s
Rendering [===>----------------------------------------------] at 22 fps ~ eta:  4s
Rendering [====>---------------------------------------------] at 22 fps ~ eta:  4s
Rendering [=====>--------------------------------------------] at 22 fps ~ eta:  4s
Rendering [=====>--------------------------------------------] at 23 fps ~ eta:  4s
Rendering [======>-------------------------------------------] at 23 fps ~ eta:  4s
Rendering [=======>------------------------------------------] at 22 fps ~ eta:  4s
Rendering [========>-----------------------------------------] at 22 fps ~ eta:  4s
Rendering [=========>----------------------------------------] at 22 fps ~ eta:  4s
Rendering [==========>---------------------------------------] at 22 fps ~ eta:  4s
Rendering [===========>--------------------------------------] at 22 fps ~ eta:  4s
Rendering [===========>--------------------------------------] at 22 fps ~ eta:  3s
Rendering [============>-------------------------------------] at 22 fps ~ eta:  3s
Rendering [=============>------------------------------------] at 22 fps ~ eta:  3s
Rendering [==============>-----------------------------------] at 22 fps ~ eta:  3s
Rendering [===============>----------------------------------] at 22 fps ~ eta:  3s
Rendering [================>---------------------------------] at 22 fps ~ eta:  3s
Rendering [=================>--------------------------------] at 22 fps ~ eta:  3s
Rendering [=================>--------------------------------] at 23 fps ~ eta:  3s
Rendering [==================>-------------------------------] at 22 fps ~ eta:  3s
Rendering [===================>------------------------------] at 22 fps ~ eta:  3s
Rendering [===================>------------------------------] at 23 fps ~ eta:  3s
Rendering [====================>-----------------------------] at 23 fps ~ eta:  3s
Rendering [=====================>----------------------------] at 23 fps ~ eta:  3s
Rendering [=====================>----------------------------] at 23 fps ~ eta:  2s
Rendering [======================>---------------------------] at 23 fps ~ eta:  2s
Rendering [=======================>--------------------------] at 23 fps ~ eta:  2s
Rendering [=======================>--------------------------] at 22 fps ~ eta:  2s
Rendering [========================>-------------------------] at 23 fps ~ eta:  2s
Rendering [=========================>------------------------] at 23 fps ~ eta:  2s
Rendering [==========================>-----------------------] at 23 fps ~ eta:  2s
Rendering [===========================>----------------------] at 23 fps ~ eta:  2s
Rendering [============================>---------------------] at 23 fps ~ eta:  2s
Rendering [=============================>--------------------] at 23 fps ~ eta:  2s
Rendering [==============================>-------------------] at 23 fps ~ eta:  2s
Rendering [===============================>------------------] at 23 fps ~ eta:  2s
Rendering [================================>-----------------] at 23 fps ~ eta:  2s
Rendering [=================================>----------------] at 23 fps ~ eta:  1s
Rendering [==================================>---------------] at 23 fps ~ eta:  1s
Rendering [===================================>--------------] at 23 fps ~ eta:  1s
Rendering [====================================>-------------] at 23 fps ~ eta:  1s
Rendering [=====================================>------------] at 23 fps ~ eta:  1s
Rendering [======================================>-----------] at 23 fps ~ eta:  1s
Rendering [=======================================>----------] at 23 fps ~ eta:  1s
Rendering [========================================>---------] at 23 fps ~ eta:  1s
Rendering [=========================================>--------] at 23 fps ~ eta:  1s
Rendering [==========================================>-------] at 23 fps ~ eta:  1s
Rendering [===========================================>------] at 23 fps ~ eta:  1s
Rendering [===========================================>------] at 23 fps ~ eta:  0s
Rendering [============================================>-----] at 23 fps ~ eta:  0s
Rendering [=============================================>----] at 23 fps ~ eta:  0s
Rendering [==============================================>---] at 23 fps ~ eta:  0s
Rendering [===============================================>--] at 23 fps ~ eta:  0s
Rendering [================================================>-] at 23 fps ~ eta:  0s
Rendering [=================================================>] at 23 fps ~ eta:  0s
Rendering [==================================================] at 23 fps ~ eta:  0s
                                                                                   


Inserting image 1 at 0.00s (1%)...
Inserting image 2 at 0.10s (2%)...
Inserting image 3 at 0.20s (3%)...
Inserting image 4 at 0.30s (4%)...
Inserting image 5 at 0.40s (5%)...
Inserting image 6 at 0.50s (6%)...
Inserting image 7 at 0.60s (7%)...
Inserting image 8 at 0.70s (8%)...
Inserting image 9 at 0.80s (9%)...
Inserting image 10 at 0.90s (10%)...
Inserting image 11 at 1.00s (11%)...
Inserting image 12 at 1.10s (12%)...
Inserting image 13 at 1.20s (13%)...
Inserting image 14 at 1.30s (14%)...
Inserting image 15 at 1.40s (15%)...
Inserting image 16 at 1.50s (16%)...
Inserting image 17 at 1.60s (17%)...
Inserting image 18 at 1.70s (18%)...
Inserting image 19 at 1.80s (19%)...
Inserting image 20 at 1.90s (20%)...
Inserting image 21 at 2.00s (21%)...
Inserting image 22 at 2.10s (22%)...
Inserting image 23 at 2.20s (23%)...
Inserting image 24 at 2.30s (24%)...
Inserting image 25 at 2.40s (25%)...
Inserting image 26 at 2.50s (26%)...
Inserting image 27 at 2.60s (27%)...
Inserting image 28 at 2.70s (28%)...
Inserting image 29 at 2.80s (29%)...
Inserting image 30 at 2.90s (30%)...
Inserting image 31 at 3.00s (31%)...
Inserting image 32 at 3.10s (32%)...
Inserting image 33 at 3.20s (33%)...
Inserting image 34 at 3.30s (34%)...
Inserting image 35 at 3.40s (35%)...
Inserting image 36 at 3.50s (36%)...
Inserting image 37 at 3.60s (37%)...
Inserting image 38 at 3.70s (38%)...
Inserting image 39 at 3.80s (39%)...
Inserting image 40 at 3.90s (40%)...
Inserting image 41 at 4.00s (41%)...
Inserting image 42 at 4.10s (42%)...
Inserting image 43 at 4.20s (43%)...
Inserting image 44 at 4.30s (44%)...
Inserting image 45 at 4.40s (45%)...
Inserting image 46 at 4.50s (46%)...
Inserting image 47 at 4.60s (47%)...
Inserting image 48 at 4.70s (48%)...
Inserting image 49 at 4.80s (49%)...
Inserting image 50 at 4.90s (50%)...
Inserting image 51 at 5.00s (51%)...
Inserting image 52 at 5.10s (52%)...
Inserting image 53 at 5.20s (53%)...
Inserting image 54 at 5.30s (54%)...
Inserting image 55 at 5.40s (55%)...
Inserting image 56 at 5.50s (56%)...
Inserting image 57 at 5.60s (57%)...
Inserting image 58 at 5.70s (58%)...
Inserting image 59 at 5.80s (59%)...
Inserting image 60 at 5.90s (60%)...
Inserting image 61 at 6.00s (61%)...
Inserting image 62 at 6.10s (62%)...
Inserting image 63 at 6.20s (63%)...
Inserting image 64 at 6.30s (64%)...
Inserting image 65 at 6.40s (65%)...
Inserting image 66 at 6.50s (66%)...
Inserting image 67 at 6.60s (67%)...
Inserting image 68 at 6.70s (68%)...
Inserting image 69 at 6.80s (69%)...
Inserting image 70 at 6.90s (70%)...
Inserting image 71 at 7.00s (71%)...
Inserting image 72 at 7.10s (72%)...
Inserting image 73 at 7.20s (73%)...
Inserting image 74 at 7.30s (74%)...
Inserting image 75 at 7.40s (75%)...
Inserting image 76 at 7.50s (76%)...
Inserting image 77 at 7.60s (77%)...
Inserting image 78 at 7.70s (78%)...
Inserting image 79 at 7.80s (79%)...
Inserting image 80 at 7.90s (80%)...
Inserting image 81 at 8.00s (81%)...
Inserting image 82 at 8.10s (82%)...
Inserting image 83 at 8.20s (83%)...
Inserting image 84 at 8.30s (84%)...
Inserting image 85 at 8.40s (85%)...
Inserting image 86 at 8.50s (86%)...
Inserting image 87 at 8.60s (87%)...
Inserting image 88 at 8.70s (88%)...
Inserting image 89 at 8.80s (89%)...
Inserting image 90 at 8.90s (90%)...
Inserting image 91 at 9.00s (91%)...
Inserting image 92 at 9.10s (92%)...
Inserting image 93 at 9.20s (93%)...
Inserting image 94 at 9.30s (94%)...
Inserting image 95 at 9.40s (95%)...
Inserting image 96 at 9.50s (96%)...
Inserting image 97 at 9.60s (97%)...
Inserting image 98 at 9.70s (98%)...
Inserting image 99 at 9.80s (99%)...
Inserting image 100 at 9.90s (100%)...
Encoding to gif... done!

Animate –> Line Plot

## filtering out only 'CHIS', 'DEVA' AND 'JOTR' Park_code
d = ca %>%
    filter(code%in%c('CHIS', 'DEVA', 'JOTR'))
d
line_plot = ggplot(d, aes(x=year, y=visitors, group=code, color=code)) + 
                   geom_line() + geom_point() + 
                   transition_reveal(year)

animate(line_plot, width=300, height=300, renderer = gifski_renderer())

Rendering [>---------------------------------] at 13 fps ~ eta:  8s
Rendering [>---------------------------------] at 13 fps ~ eta:  7s
Rendering [=>--------------------------------] at 13 fps ~ eta:  7s
Rendering [=>--------------------------------] at 12 fps ~ eta:  7s
Rendering [==>-------------------------------] at 13 fps ~ eta:  7s
Rendering [===>------------------------------] at 13 fps ~ eta:  7s
Rendering [===>------------------------------] at 12 fps ~ eta:  7s
Rendering [====>-----------------------------] at 13 fps ~ eta:  7s
Rendering [====>-----------------------------] at 12 fps ~ eta:  7s
Rendering [====>-----------------------------] at 13 fps ~ eta:  7s
Rendering [=====>----------------------------] at 13 fps ~ eta:  7s
Rendering [=====>----------------------------] at 13 fps ~ eta:  6s
Rendering [======>---------------------------] at 13 fps ~ eta:  6s
Rendering [=======>--------------------------] at 13 fps ~ eta:  6s
Rendering [========>-------------------------] at 13 fps ~ eta:  6s
Rendering [=========>------------------------] at 13 fps ~ eta:  6s
Rendering [=========>------------------------] at 13 fps ~ eta:  5s
Rendering [==========>-----------------------] at 13 fps ~ eta:  5s
Rendering [===========>----------------------] at 13 fps ~ eta:  5s
Rendering [============>---------------------] at 13 fps ~ eta:  5s
Rendering [=============>--------------------] at 13 fps ~ eta:  5s
Rendering [=============>--------------------] at 13 fps ~ eta:  4s
Rendering [==============>-------------------] at 13 fps ~ eta:  4s
Rendering [===============>------------------] at 13 fps ~ eta:  4s
Rendering [================>-----------------] at 13 fps ~ eta:  4s
Rendering [=================>----------------] at 13 fps ~ eta:  4s
Rendering [==================>---------------] at 13 fps ~ eta:  3s
Rendering [===================>--------------] at 13 fps ~ eta:  3s
Rendering [====================>-------------] at 13 fps ~ eta:  3s
Rendering [=====================>------------] at 13 fps ~ eta:  3s
Rendering [======================>-----------] at 13 fps ~ eta:  3s
Rendering [======================>-----------] at 13 fps ~ eta:  2s
Rendering [=======================>----------] at 13 fps ~ eta:  2s
Rendering [========================>---------] at 13 fps ~ eta:  2s
Rendering [=========================>--------] at 13 fps ~ eta:  2s
Rendering [==========================>-------] at 13 fps ~ eta:  2s
Rendering [==========================>-------] at 13 fps ~ eta:  1s
Rendering [===========================>------] at 13 fps ~ eta:  1s
Rendering [============================>-----] at 13 fps ~ eta:  1s
Rendering [=============================>----] at 13 fps ~ eta:  1s
Rendering [==============================>---] at 13 fps ~ eta:  1s
Rendering [===============================>--] at 13 fps ~ eta:  1s
Rendering [===============================>--] at 13 fps ~ eta:  0s
Rendering [================================>-] at 13 fps ~ eta:  0s
Rendering [=================================>] at 13 fps ~ eta:  0s
Rendering [==================================] at 13 fps ~ eta:  0s
                                                                   


Inserting image 1 at 0.00s (1%)...
Inserting image 2 at 0.10s (2%)...
Inserting image 3 at 0.20s (3%)...
Inserting image 4 at 0.30s (4%)...
Inserting image 5 at 0.40s (5%)...
Inserting image 6 at 0.50s (6%)...
Inserting image 7 at 0.60s (7%)...
Inserting image 8 at 0.70s (8%)...
Inserting image 9 at 0.80s (9%)...
Inserting image 10 at 0.90s (10%)...
Inserting image 11 at 1.00s (11%)...
Inserting image 12 at 1.10s (12%)...
Inserting image 13 at 1.20s (13%)...
Inserting image 14 at 1.30s (14%)...
Inserting image 15 at 1.40s (15%)...
Inserting image 16 at 1.50s (16%)...
Inserting image 17 at 1.60s (17%)...
Inserting image 18 at 1.70s (18%)...
Inserting image 19 at 1.80s (19%)...
Inserting image 20 at 1.90s (20%)...
Inserting image 21 at 2.00s (21%)...
Inserting image 22 at 2.10s (22%)...
Inserting image 23 at 2.20s (23%)...
Inserting image 24 at 2.30s (24%)...
Inserting image 25 at 2.40s (25%)...
Inserting image 26 at 2.50s (26%)...
Inserting image 27 at 2.60s (27%)...
Inserting image 28 at 2.70s (28%)...
Inserting image 29 at 2.80s (29%)...
Inserting image 30 at 2.90s (30%)...
Inserting image 31 at 3.00s (31%)...
Inserting image 32 at 3.10s (32%)...
Inserting image 33 at 3.20s (33%)...
Inserting image 34 at 3.30s (34%)...
Inserting image 35 at 3.40s (35%)...
Inserting image 36 at 3.50s (36%)...
Inserting image 37 at 3.60s (37%)...
Inserting image 38 at 3.70s (38%)...
Inserting image 39 at 3.80s (39%)...
Inserting image 40 at 3.90s (40%)...
Inserting image 41 at 4.00s (41%)...
Inserting image 42 at 4.10s (42%)...
Inserting image 43 at 4.20s (43%)...
Inserting image 44 at 4.30s (44%)...
Inserting image 45 at 4.40s (45%)...
Inserting image 46 at 4.50s (46%)...
Inserting image 47 at 4.60s (47%)...
Inserting image 48 at 4.70s (48%)...
Inserting image 49 at 4.80s (49%)...
Inserting image 50 at 4.90s (50%)...
Inserting image 51 at 5.00s (51%)...
Inserting image 52 at 5.10s (52%)...
Inserting image 53 at 5.20s (53%)...
Inserting image 54 at 5.30s (54%)...
Inserting image 55 at 5.40s (55%)...
Inserting image 56 at 5.50s (56%)...
Inserting image 57 at 5.60s (57%)...
Inserting image 58 at 5.70s (58%)...
Inserting image 59 at 5.80s (59%)...
Inserting image 60 at 5.90s (60%)...
Inserting image 61 at 6.00s (61%)...
Inserting image 62 at 6.10s (62%)...
Inserting image 63 at 6.20s (63%)...
Inserting image 64 at 6.30s (64%)...
Inserting image 65 at 6.40s (65%)...
Inserting image 66 at 6.50s (66%)...
Inserting image 67 at 6.60s (67%)...
Inserting image 68 at 6.70s (68%)...
Inserting image 69 at 6.80s (69%)...
Inserting image 70 at 6.90s (70%)...
Inserting image 71 at 7.00s (71%)...
Inserting image 72 at 7.10s (72%)...
Inserting image 73 at 7.20s (73%)...
Inserting image 74 at 7.30s (74%)...
Inserting image 75 at 7.40s (75%)...
Inserting image 76 at 7.50s (76%)...
Inserting image 77 at 7.60s (77%)...
Inserting image 78 at 7.70s (78%)...
Inserting image 79 at 7.80s (79%)...
Inserting image 80 at 7.90s (80%)...
Inserting image 81 at 8.00s (81%)...
Inserting image 82 at 8.10s (82%)...
Inserting image 83 at 8.20s (83%)...
Inserting image 84 at 8.30s (84%)...
Inserting image 85 at 8.40s (85%)...
Inserting image 86 at 8.50s (86%)...
Inserting image 87 at 8.60s (87%)...
Inserting image 88 at 8.70s (88%)...
Inserting image 89 at 8.80s (89%)...
Inserting image 90 at 8.90s (90%)...
Inserting image 91 at 9.00s (91%)...
Inserting image 92 at 9.10s (92%)...
Inserting image 93 at 9.20s (93%)...
Inserting image 94 at 9.30s (94%)...
Inserting image 95 at 9.40s (95%)...
Inserting image 96 at 9.50s (96%)...
Inserting image 97 at 9.60s (97%)...
Inserting image 98 at 9.70s (98%)...
Inserting image 99 at 9.80s (99%)...
Inserting image 100 at 9.90s (100%)...
Encoding to gif... done!

Visitors started to visit Channel Islands National Park in 1960’s (latest among) has very low visitors till date. Joshua Tree National Park has a continuous growth of visitors without a big drop. Death Valley National Park has a continuous growth of visitors in 2010’s and a gradual pick-up.

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKQWR2YW5jZWQgRGF0YSBWaXN1YWxpemF0aW9uIFRoZW9yeSBEQS0xClByYXNoYW50aC5TIAoxOU1JRDAwMjAKCkRhdGEtc2V0cyB1c2VkIApkYXRhLXNldDEgOiBodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vU2NpZW5jZVBhcmtTdHVkeUdyb3VwL3ItbGVzc29uLWJhc2VkLW9uLW9oaS1kYXRhLXRyYWluaW5nL2doLXBhZ2VzL2RhdGEvY2EuY3N2CmRhdC1zZXQgMjogaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9jb2RlL2FkaG9rOTMvem9tYXRvLWVkYS1pbi1yL2RhdGE/c2VsZWN0PXpvbWF0by5jc3YKCgojIyBJbXBvcnRpbmcgdGhlIGxpYnJhcmllcwpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocGxvdGx5KQoKcmVxdWlyZShkZXZ0b29scykKYGBgCiMjIFVTIE5hdGlvbmFsIFBhcmtzIGRhdGEtc2V0CgojIyBJbXBvcnRpbmcgdGhlIGRhdGEtc2V0CmBgYHtyfQojIE5hdGlvbmFsIFBhcmtzIGluIENhbGlmb3JuaWEKY2EgPSByZWFkX2NzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL1NjaWVuY2VQYXJrU3R1ZHlHcm91cC9yLWxlc3Nvbi1iYXNlZC1vbi1vaGktZGF0YS10cmFpbmluZy9naC1wYWdlcy9kYXRhL2NhLmNzdiIpIAoKaGVhZChjYSkKYGBgCgojIyBBbmFseXNpbmcgdGhlIGRhdGEtdHlwZSBvZiB0aGUgZGF0YQpgYGB7cn0KY29sbmFtZXMoY2EpCmBgYAoKYGBge3J9CnN0cihjYSkKYGBgCgojIyBQbG90LTEgLS0+IGdncGxvdDIKIyMjIEJhciBQbG90CmBgYHtyfQpsYWJzID0gYygKICAgICAgICAgJ0NISVMnPSdDaGFubmVsIElzbGFuZHMgTmF0aW9uYWwgUGFyaycsCiAgICAgICAgICdERVZBJz0nRGVhdGggVmFsbGV5IE5hdGlvbmFsIFBhcmsnLAogICAgICAgICAnSk9UUic9J0pvc2h1YSBUcmVlIE5hdGlvbmFsIFBhcmsnLAogICAgICAgICAnS0lDQSc9J0tpbmdzIENhbnlvbiBOYXRpb25hbCBQYXJrJywKICAgICAgICAgJ0xBVk8nPSdMYXNzZW4gVm9sY2FuaWMgTmF0aW9uYWwgUGFyaycsCiAgICAgICAgICdZT1NFJz0nWW9zZW1pdGUgTmF0aW9uYWwgUGFyaycsCiAgICAgICAgICdTRVFVJz0nU2VxdW9pYSBOYXRpb25hbCBQYXJrJywKICAgICAgICAgJ1JFRFcnPSdSZWR3b29kIE5hdGlvbmFsIFBhcmsnLAogICAgICAgICAnUElOTic9J1Bpbm5hY2xlcyBOYXRpb25hbCBQYXJrJwogICAgICAgICApCmBgYAoKCmBgYHtyfQpiYXJfcGxvdCA9IGdncGxvdChkYXRhPWNhLCBhZXMoeCA9IGNvZGUsIHkgPSAuLmNvdW50Li4gLyBzdW0oLi5jb3VudC4uKSxmaWxsID0gZmFjdG9yKGNvZGUpKSkgKwogICAgICAgICAgIGdlb21fYmFyKGNvbG9yPSdibGFjaycpICsgCiAgICAgICAgICAgbGFicyh4ID0gIk5hdGlvbmFsIFBhcmtzIiwgeSA9ICJQZXJjZW50YWdlIG9mIE5hdGlvbmFsIFBhcmtzIGluIHRoZSBkYXRhLXNldCIsIAogICAgICAgICAgICAgICAgdGl0bGUgPSAiT2NjdXJlbmNlIG9mIHRoZSBOYXRpb25hbCBQYXJrcyBpbiB0aGUgZGF0YS1zZXQiKSArCiAgCiAgICAgICAgICAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHMgPWxhYnMpCiAgICAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudCkKICAgICAgICAgICAKYmFyX3Bsb3QgKyBjb29yZF9mbGlwKCkKYGBgCllvc2VtaXRlIE5hdGlvbmFsIFBhcmtzIGFuZCBTZXF1b2lhIE5hdGlvbmFsIFBhcmsgb2NjdXJzIG1vcmUgb2Z0ZW4gaW4gdGhlIGRhdGEtc2V0CgojIyMgS2VybmVsIERlbnNpdHkgUGxvdApgYGB7cn0KZGVuc2l0eV9wbG90ID0gZ2dwbG90KGRhdGE9Y2EsIGFlcyh4ID1sb2cxMCh2aXNpdG9ycykpKSArCiAgICAgICAgICAgICAgICBnZW9tX2RlbnNpdHkoZmlsbCA9ICJpbmRpYW5yZWQzIikgKwogICAgICAgICAgICAgICAgbGFicyh4ID0gIk51bWJlciBvZiB2aXNpdG9ycyIsIHk9ImRlbnNpdHkiLCB0aXRsZT0iS2VybmFsIGRlbnNpdHkgb2YgVmlzaXRvcnMiKQpkZW5zaXR5X3Bsb3QgICAgICAgCmBgYAojIyBQbG90LTIgLS0+IHBsb3RseQojIyMgU2NhdHRlciBwbG90CgpgYGB7cn0KdCA8LSBsaXN0KGZhbWlseSA9ICJIZWx2ZXRpY2EiLHNpemUgPSAxNCxjb2xvciA9ICJibHVlIikKdDEgPC0gbGlzdChmYW1pbHkgPSAiVGltZXMgTmV3IFJvbWFuIixjb2xvciA9ICJyZWQiKQp0MiA8LSBsaXN0KGZhbWlseSA9ICJDb3VyaWVyIE5ldyIsc2l6ZSA9IDE0LGNvbG9yID0gImdyZWVuIikKdDMgPC0gbGlzdChmYW1pbHkgPSAnQXJpYWwnKQpgYGAKCmBgYHtyfQpzY2F0dGVyX3Bsb3QgPSBwbG90X2x5KGRhdGE9Y2EsIHg9fnllYXIsIHk9fnZpc2l0b3JzLGNvbG9yID0gfnBhcmtfbmFtZSwgdHlwZT0nc2NhdHRlcicsbW9kZT0nbWFya2VycycpICU+JQogICAgICAgICAgICAgICAgICAgICAgIGxheW91dCgKICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZT0gbGlzdCh0ZXh0ID0gIjxiPlllYXIgYW5kIFZpc2l0b3JzIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgbGVnZW5kID0gbGlzdCh0aXRsZSA9IGxpc3QodGV4dCA9JzxiPk5hdGlvbmFsIFBhcmtzJykpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB4YXhpcyAgPSBsaXN0KHRpdGxlID0gbGlzdCh0ZXh0ID0nPGI+WWVhcicpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5YXhpcyAgPSBsaXN0KHRpdGxlID0gbGlzdCh0ZXh0ID0nPGI+VmlzaXRvcnMnKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgcGxvdF9iZ2NvbG9yPScjZTVlY2Y2JykKc2NhdHRlcl9wbG90CmBgYApZb3NlbWl0ZSBOYXRpb25hbCBQYXJrIHNlY3VyZXMgYSBtb3JlIG51bWJlciBvZiB2aXNpdG9ycyB0aGFuIGFueS1vdGhlciBuYXRpb25hbCBwYXJrcy4KCiMjIyBCYXJjaGFydApgYGB7cn0Kcl9ncm91cF9iYXJjaGFydCA9IGRhdGEudGFibGU6Om1lbHQoY2EsIGlkLnZhcnM9J3BhcmtfbmFtZScpICU+JQpwbG90X2x5KHggPSB+cGFya19uYW1lLCB5ID0gfnZhbHVlLCB0eXBlID0gJ2JhcicsIG5hbWUgPSB+dmFyaWFibGUsIGNvbG9yID0gfnZhcmlhYmxlKSAlPiUKICAgICAgbGF5b3V0KAogICAgICAgICAgdGl0bGU9IGxpc3QodGV4dCA9ICI8Yj5Ub3RhbCBEaXN0cmlidXRpb24gYmFzZWQgb24gdGhlIERhdGEtU2V0IiksCiAgICAgICAgICBsZWdlbmQgPSBsaXN0KHRpdGxlID0gbGlzdCh0ZXh0PSAnPGI+QXR0cmlidXRlJykpLAogICAgICAgICAgeGF4aXMgID0gbGlzdCh0aXRsZSA9IGxpc3QodGV4dCA9JzxiPlBhcmtzJykpLAogICAgICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlPSdDb3VudCcsIHRleHQ9JzxiPkNvdW50JyksIGJhcm1vZGUgPSAnZ3JvdXAnKQpyX2dyb3VwX2JhcmNoYXJ0CmBgYApLaW5ncyBDYW55b24gTmF0aW9uYWwgUGFyayBzZWN1cmVzIHRoZSB0b3AgaW4gdGVybXMgb2YgcmVnaW9uLCBzdGF0ZSwgbmF0aW9uYWwgcGFyay4KCiMjIyBQaWUtY2hhcnQKYGBge3J9CmRmX29yZGVyID0gZGF0YS5mcmFtZSh0YWJsZShjYSRwYXJrX25hbWUpKQpkZl9vcmRlcgpgYGAKCmBgYHtyfQpwaWVfY2hhcnQgPSBwbG90X2x5KHR5cGU9J3BpZScsIGxhYmVscz1kZl9vcmRlciRWYXIxLCB2YWx1ZXM9ZGZfb3JkZXIkRnJlcSwgCiAgICAgICAgICAgICAgICAgICAgdGV4dGluZm89J2xhYmVsK3BlcmNlbnQnLGluc2lkZXRleHRvcmllbnRhdGlvbj0ncmFkaWFsJykgJT4lCiAgICAgICAgICAgICAgICAgICAgbGF5b3V0KAogICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlPSBsaXN0KHRleHQgPSAiPGI+T3JkZXIgRGlzdHJpYnV0aW9ucyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZCA9IGxpc3QodGl0bGUgPSBsaXN0KHRleHQ9ICc8Yj5PcmRlcicpKSkKCnBpZV9jaGFydApgYGAKCiMjIyBIaXN0b2dyYW0gUGxvdHMKYGBge3J9Cmhpc3RvZ3JhbV9wbG90ID0gcGxvdF9seShkYXRhID0gY2EsIHggPSB+KGxvZyh2aXNpdG9ycykpLCBuYW1lPX5jb2RlLHR5cGU9Imhpc3RvZ3JhbSIpICU+JQogICAgICAgICAgICAgICAgICBsYXlvdXQoCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU9IGxpc3QodGV4dCA9ICI8Yj5Ub3RhbCBzbGVlcCB0aW1lIG9mIEFuaW1hbHMgYmFzZWQgb24gVm9yZSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxlZ2VuZCA9IGxpc3QodGl0bGUgPSBsaXN0KHRleHQ9ICc8Yj5Wb3JlJykpLAogICAgICAgICAgICAgICAgICAgICAgICAgIHhheGlzICA9IGxpc3QodGl0bGUgPSBsaXN0KHRleHQgPSc8Yj5WaXNpdG9ycycpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICB5YXhpcyAgPSBsaXN0KHRpdGxlID0gbGlzdCh0ZXh0ID0nPGI+Q291bnQnKSkpCmhpc3RvZ3JhbV9wbG90CmBgYAoKU0VRVSBhbmQgTEFWTyBuYXRpb25hbCBwYXJrcyBoYXMgbW9yZSBudW1iZXIgb2YgdmlzaXRvcnMKCiMjIyBEb251dCBDaGFydCAvIE9wZW4gUGllLUNoYXJ0CmBgYHtyfQpkZl92b3JlID0gZGF0YS5mcmFtZSh0YWJsZShjYSRjb2RlKSkKZGZfdm9yZQpgYGAKCmBgYHtyfQpkb251dF9jaGFydCA9IHBsb3RfbHkobGFiZWxzPWRmX3ZvcmUkVmFyMSwgdmFsdWVzPWRmX3ZvcmUkRnJlcSwgCiAgICAgICAgICAgICAgICAgICAgdGV4dGluZm89J2xhYmVsK3BlcmNlbnQnKSAlPiUKICAgICAgICAgICAgICAgICAgICBhZGRfcGllKGhvbGUgPSAwLjYpICU+JQogICAgICAgICAgICAgICAgICAgIGxheW91dCgKICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZT0gbGlzdCh0ZXh0ID0gIjxiPk9yZGVyIERpc3RyaWJ1dGlvbnMiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBsZWdlbmQgPSBsaXN0KHRpdGxlID0gbGlzdCh0ZXh0PSAnPGI+T3JkZXInKSkpCgpkb251dF9jaGFydApgYGAKClNFUVUsIFlPU0UgYW5kIEtJQ0EgbmF0aW9uYWwgcGFya3MgaGFzIG1vcmUgbnVtYmVyIG9mIHZpc2l0b3JzIHdpdGggcmVzcGVjdCB0byBwaWUtY2hhcnQuCgojIyBab21hdG8gZGF0YS1zZXQKCiMjIEltcG9ydGluZyB0aGUgZGF0YS1zZXQKYGBge3J9CmxpYnJhcnkoZHBseXIpCmBgYAoKIyMgSW1wb3J0aW5nIHRoZSBkYXRhLXNldApgYGB7cn0KZGYgPSByZWFkLmNzdignem9tYXRvLmNzdicpCmhlYWQoZGYpCmBgYAoKIyMgQW5hbHlzaW5nIHRoZSBkYXRhLXR5cGUgb2YgdGhlIGRhdGEKYGBge3J9Cm5hbWVzKGRmKQpgYGAKCmBgYHtyfQpzdHIoZGYpCmBgYAoKYGBge3J9CmJhcl9wbG90ID0gZ2dwbG90KGRhdGE9ZGYsIGFlcyh4ID0gYFJhdGluZy5jb2xvcmAsIHkgPSAuLmNvdW50Li4gLyBzdW0oLi5jb3VudC4uKSxmaWxsID0gZmFjdG9yKGBSYXRpbmcuY29sb3JgKSkpICsKICAgICAgICAgICBnZW9tX2Jhcihjb2xvcj0nYmxhY2snKSArIAogICAgICAgICAgIGxhYnMoeCA9ICJOYXRpb25hbCBQYXJrcyIsIHkgPSAiUGVyY2VudGFnZSBvZiBOYXRpb25hbCBQYXJrcyBpbiB0aGUgZGF0YS1zZXQiLCAKICAgICAgICAgICAgICAgIHRpdGxlID0gIk9jY3VyZW5jZSBvZiB0aGUgTmF0aW9uYWwgUGFya3MgaW4gdGhlIGRhdGEtc2V0IikgKwogIAogICAgICAgICAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnQpCiAgICAgICAgICAgCmJhcl9wbG90ICsgY29vcmRfZmxpcCgpCmBgYAoKYGBge3J9CmRmICU+JQogIGZpbHRlcihDb3VudHJ5LkNvZGUgPT0gMSkgJT4lCiAgc2VsZWN0KFJlc3RhdXJhbnQuSUQpICU+JQogIHVuaXF1ZSgpICU+JQogIG5yb3coKQpgYGAKVGhlcmUgYXJlIDg2NTIgcmVzdGF1cmFudHMgb3BlcmF0aW5nIGluIEluZGlhCgpgYGB7cn0KZGYgJT4lIGZpbHRlcihDb3VudHJ5LkNvZGUgPT0gMSkgJT4lIHNlbGVjdChSZXN0YXVyYW50LklELENpdHkpICU+JSB1bmlxdWUoKSAlPiUgZ3JvdXBfYnkoQ2l0eSkgJT4lIHN1bW1hcmlzZShuPW4oKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXJlb3JkZXIoYENpdHlgLG4pLHk9bikpKyBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JyxmaWxsPScjY2IyMDJkJykgKwogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWUocGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoY29sb3IgPSAnIzJkMmQyZCcpLAogICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvcj0nIzJkMmQyZCcsZmFjZT0nYm9sZCcsc2l6ZT0xMCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdD0wLjUsZmFjZT0nYm9sZCcsc2l6ZT0xNSkpKwogICAgICAgIGxhYnMoeD0nQ2l0eScseT0nTnVtYmVyIG9mIFJlc3RhdXJhbnRzJyx0aXRsZT0iTnVtYmVyIG9mIFJlc3RhdXJhbnRzIGJ5IENpdHkiKQpgYGAKVGhlcmUgYXJlIG1vcmUgcmVzdGF1cmFudHMgaW4gRGVsaGkgd2hpY2ggb3BlcmF0ZXMgd2l0aCBab21hdG8KCmBgYHtyfQpkZl9pbmRpYSA9IGRmICU+JSBmaWx0ZXIoQ291bnRyeS5Db2RlID09IDEgJiBDaXR5ID09ICdBZ3JhJykKaGVhZChkZl9pbmRpYSkKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGE9ZGZfaW5kaWEsIGFlcyh4PUxvbmdpdHVkZSwgeT1MYXRpdHVkZSksCiAgICAgICBjb2xvcj0nd2hpdGUnKSArIAogICAgICAgZ2VvbV9wb2x5Z29uKCkgKyAKICAgICAgIHNjYWxlX2ZpbGxfdmlyaWRpc19kKG9wdGlvbj0nQScpCmBgYAoKIyMgUGxvdC00IC0tPiBnZ2FuaW1hdGUKYGBge3J9CmxpYnJhcnkoZ2dhbmltYXRlKQpsaWJyYXJ5KGdpZnNraSkKYGBgCgojIyMgQW5pbWF0ZSAtLT4gU2NhdHRlciBQbG90CmBgYHtyfQpzY2F0dGVyX3Bsb3RfYW5pbWF0ZSA9IGdncGxvdChkYXRhPWNhLCBhZXMoeWVhciwgdmlzaXRvcnMpKSArIGdlb21fcG9pbnQoKSArICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb25fc3RhdGVzKHBhcmtfbmFtZSkKCmFuaW1hdGUoc2NhdHRlcl9wbG90X2FuaW1hdGUsIHJlbmRlcmVyID0gZ2lmc2tpX3JlbmRlcmVyKCkpCmBgYAoKIyMjIEFuaW1hdGUgLS0+IExpbmUgUGxvdApgYGB7cn0KIyMgZmlsdGVyaW5nIG91dCBvbmx5ICdDSElTJywgJ0RFVkEnIEFORCAnSk9UUicgUGFya19jb2RlCmQgPSBjYSAlPiUKICAgIGZpbHRlcihjb2RlJWluJWMoJ0NISVMnLCAnREVWQScsICdKT1RSJykpCmQKYGBgCgpgYGB7cn0KbGluZV9wbG90ID0gZ2dwbG90KGQsIGFlcyh4PXllYXIsIHk9dmlzaXRvcnMsIGdyb3VwPWNvZGUsIGNvbG9yPWNvZGUpKSArIAogICAgICAgICAgICAgICAgICAgZ2VvbV9saW5lKCkgKyBnZW9tX3BvaW50KCkgKyAKICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb25fcmV2ZWFsKHllYXIpCgphbmltYXRlKGxpbmVfcGxvdCwgd2lkdGg9MzAwLCBoZWlnaHQ9MzAwLCByZW5kZXJlciA9IGdpZnNraV9yZW5kZXJlcigpKQpgYGAKVmlzaXRvcnMgc3RhcnRlZCB0byB2aXNpdCBDaGFubmVsIElzbGFuZHMgTmF0aW9uYWwgUGFyayBpbiAxOTYwJ3MgKGxhdGVzdCBhbW9uZykgaGFzIHZlcnkgbG93IHZpc2l0b3JzIHRpbGwgZGF0ZS4KSm9zaHVhIFRyZWUgTmF0aW9uYWwgUGFyayBoYXMgYSBjb250aW51b3VzIGdyb3d0aCBvZiB2aXNpdG9ycyB3aXRob3V0IGEgYmlnIGRyb3AuCkRlYXRoIFZhbGxleSBOYXRpb25hbCBQYXJrIGhhcyBhIGNvbnRpbnVvdXMgZ3Jvd3RoIG9mIHZpc2l0b3JzIGluIDIwMTAncyBhbmQgYSBncmFkdWFsIHBpY2stdXAuCg==